/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package co.com.claro.administracionSolicitudes.dao;

import co.com.claro.administracionSolicitudes.dao.exceptions.NonexistentEntityException;
import co.com.claro.administracionSolicitudes.dao.exceptions.RollbackFailureException;
import co.com.claro.administracionSolicitudes.dto.PrivilegioSolicitudDto;
import java.io.Serializable;
import javax.persistence.Query;
import javax.persistence.EntityNotFoundException;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import co.com.claro.administracionSolicitudes.entity.Aplicacion;
import co.com.claro.administracionSolicitudes.entity.PrivilegioSolicitud;
import co.com.claro.administracionSolicitudes.entity.enums.EstadoActividadEnum;
import co.com.claro.administracionSolicitudes.entity.enums.MovimientosEnum;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;

/**
 *
 * @author Mike
 */
public class PrivilegioSolicitudJpaController implements Serializable {

    public PrivilegioSolicitudJpaController() {

    }

    @PersistenceContext
    private EntityManager em;
    @Inject
    private HistoricoParametrosJpaController historicoJpa;

    public void create(PrivilegioSolicitud privilegioSolicitud) throws RollbackFailureException, Exception {

        try {
            em.persist(privilegioSolicitud);
            historicoJpa.create(privilegioSolicitud.crearHistorico(privilegioSolicitud, MovimientosEnum.CREAR));
        } catch (Exception ex) {
            throw ex;
        }
    }

    public void edit(PrivilegioSolicitud privilegioSolicitud) throws NonexistentEntityException, RollbackFailureException, Exception {
        String usuario = privilegioSolicitud.getUsuario();
        try {
            privilegioSolicitud = em.merge(privilegioSolicitud);
            privilegioSolicitud.setUsuario(usuario);
            historicoJpa.create(privilegioSolicitud.crearHistorico(privilegioSolicitud, MovimientosEnum.MODIFICAR));
        } catch (Exception ex) {
            throw ex;
        }
    }

    public void destroy(Integer id) throws NonexistentEntityException, RollbackFailureException, Exception {

        try {
            PrivilegioSolicitud privilegioSolicitud;
            try {
                privilegioSolicitud = em.getReference(PrivilegioSolicitud.class, id);
                historicoJpa.create(privilegioSolicitud.crearHistorico(privilegioSolicitud, MovimientosEnum.BORRAR));
            } catch (EntityNotFoundException enfe) {
                throw new NonexistentEntityException("The privilegioSolicitud with id " + id + " no longer exists.", enfe);
            }
            em.remove(privilegioSolicitud);

        } catch (Exception ex) {
            throw ex;
        }
    }

    public void borradoLogico(PrivilegioSolicitud privilegioSolicitud) throws Exception {
        String usuario = privilegioSolicitud.getUsuario();
        try {
            privilegioSolicitud.setActivo(EstadoActividadEnum.INACTIVO.getId());
            privilegioSolicitud = em.merge(privilegioSolicitud);
            privilegioSolicitud.setUsuario(usuario);
            historicoJpa.create(privilegioSolicitud.crearHistorico(privilegioSolicitud, MovimientosEnum.BORRAR));
        } catch (Exception ex) {
            throw ex;
        }
    }

    public List<PrivilegioSolicitud> findPrivilegiosNoPaginacion(PrivilegioSolicitudDto dataTransfer) {
        return findPrivilegios(false, -1, -1, dataTransfer);
    }

    public List<PrivilegioSolicitud> findPrivilegiosPaginacion(int firstResult, int maxResult) {
        return findPrivilegios(true, firstResult, maxResult, null);
    }

    public List<PrivilegioSolicitud> findPrivilegiosPaginacion(int firstResult, int maxResult, PrivilegioSolicitudDto dataTransfer) {
        return findPrivilegios(true, firstResult, maxResult, dataTransfer);
    }

    private List<PrivilegioSolicitud> findPrivilegios(boolean paginado, int firstResult, int maxResults, PrivilegioSolicitudDto dataTransfer) {
        //SELECT p FROM PrivilegioSolicitud p
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery<PrivilegioSolicitud> cQuery = builder.createQuery(PrivilegioSolicitud.class);
        Root<PrivilegioSolicitud> p = cQuery.from(PrivilegioSolicitud.class);
        cQuery.select(p);

        List<Predicate> predicados = construirPredicados(dataTransfer, p);

        if (!predicados.isEmpty()) {
            //WHERE [...]
            cQuery.where(predicados.toArray(new Predicate[0]));
        }
        if (dataTransfer.getCampoSorteado() != null) {

            if (dataTransfer.getCampoSorteado().contains(".")) {
                String[] split = dataTransfer.getCampoSorteado().split("\\.");

                Path order = p.get(split[0]);

                for (int i = 1; i < split.length; i++) {
                    order = order.get(split[i]);
                }

                //ORDER BY [...]
                if (dataTransfer.isAscendiente()) {
                    cQuery.orderBy(builder.asc(order));
                } else {
                    cQuery.orderBy(builder.desc(order));
                }

            } else {
                //ORDER BY [...]
                if (dataTransfer.isAscendiente()) {
                    cQuery.orderBy(builder.asc(p.get(dataTransfer.getCampoSorteado())));
                } else {
                    cQuery.orderBy(builder.desc(p.get(dataTransfer.getCampoSorteado())));
                }
            }
        }

        Query query = em.createQuery(cQuery);

        if (paginado) {
            query.setMaxResults(maxResults);
            query.setFirstResult(firstResult);
        }

        return query.getResultList();
    }

    private List<Predicate> construirPredicados(PrivilegioSolicitudDto dataTransfer, Root<PrivilegioSolicitud> root) {
        CriteriaBuilder builder = em.getCriteriaBuilder();

        List<Predicate> predicados = new ArrayList<Predicate>();

        Predicate idPrivilegio, idAplicacion, idGerenciaAprobadora, idPerfil, idTipoAplicacion, activo;

        if (dataTransfer.getIdAplicacion() != null) {
            // p.idPrivilegio = :idPrivilegio
            idPrivilegio = builder.equal(root.get("idPrivilegio"), dataTransfer.getIdPrivilegio());
            predicados.add(idPrivilegio);
        }
        if (dataTransfer.getIdAplicacion() != null) {
            // p.idAplicacion.idAplicacion = :idAplicacion
            idAplicacion = builder.equal(root.get("idAplicacion").get("idAplicacion"), dataTransfer.getIdAplicacion());
            predicados.add(idAplicacion);
        }
        if (dataTransfer.getIdGerenciaAprobadora() != null) {
            // p.idGerencia.idGerencia = :idGerenciaAprobadora
            idGerenciaAprobadora = builder.equal(root.get("idGerencia").get("idGerencia"), dataTransfer.getIdGerenciaAprobadora());
            predicados.add(idGerenciaAprobadora);
        }
        if (dataTransfer.getIdPerfil() != null) {
            // p.idPerfil.idPerfil = :idPerfil
            idPerfil = builder.equal(root.get("idPerfil").get("idPerfil"), dataTransfer.getIdPerfil());
            predicados.add(idPerfil);
        }
        if (dataTransfer.getIdTipoAplicacion() != null) {
            // p.idTipoSolicitud = :idTipoAplicacion
            idTipoAplicacion = builder.equal(root.get("idTipoSolicitud"), dataTransfer.getIdTipoAplicacion());
            predicados.add(idTipoAplicacion);
        }
        if (dataTransfer.getActivo() != null) {
            // p.activo = :activo
            activo = builder.equal(root.get("activo"), dataTransfer.getActivo());
            predicados.add(activo);
        }

        return predicados;
    }

    public PrivilegioSolicitud findPrivilegioSolicitud(Integer id) {
        return em.find(PrivilegioSolicitud.class, id);
    }

    /**
     * Método que obtiene todos los privilegiosa las que el usuario tiene
     * acceso.
     *
     * @param idGerencia, Gerencia a la que pertenece un usuario
     * @return List<PrivilegioSolicitud>, los privilegios (aplicaciones) a las
     * que tiene acceso
     */
    public List<PrivilegioSolicitud> findPrivilegiosPaginacion(int maxResults, int firstResult, Short activo) {
        List<PrivilegioSolicitud> privilegios = em.createNamedQuery("PrivilegioSolicitud.findPrivilegiosByActivo")
                .setParameter("activo", activo)
                .setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
        return privilegios;
    }

    /**
     * Método que obtiene los privilegios (perfiles) a las que el usuario tiene
     * acceso dependiendo de la aplicación que escoja
     *
     * @param idAplicacion, aplicación que escoje de la interfaz gráfica
     * @return List<PrivilegioSolicitud>, los privilegios (perfiles) a las que
     * tiene acceso
     */
    public List<PrivilegioSolicitud> findPrivilegioByAplicacion(int idAplicacion) {
        Aplicacion aplicacion = new Aplicacion(idAplicacion);

        List<PrivilegioSolicitud> privilegios = em.createNamedQuery("PrivilegioSolicitud.findByIdAplicacion")
                .setParameter("idAplicacion", aplicacion)
                .setParameter("activo", EstadoActividadEnum.ACTIVO.getId())
                .getResultList();
        return privilegios;
    }

    public PrivilegioSolicitud findByAplicacionPerfilGerencia(int idAplicacion, int idPerfil, int idGerencia) {
        PrivilegioSolicitud privilegiosolicitud = (PrivilegioSolicitud) em.createNamedQuery("PrivilegioSolicitud.findByAplicacionPerfilGerencia")
                .setParameter("idAplicacion", idAplicacion)
                .setParameter("idGerencia", idGerencia)
                .setParameter("idPerfil", idPerfil)
                .getSingleResult();
        return privilegiosolicitud;
    }

    public List<PrivilegioSolicitud> findByAplicacionGerencia(int idAplicacion, int idGerencia) {
        return em.createNamedQuery("PrivilegioSolicitud.findByAplicacionGerencia")
                .setParameter("idAplicacion", idAplicacion)
                .setParameter("idGerencia", idGerencia)
                .setParameter("activo", EstadoActividadEnum.ACTIVO.getId())
                .getResultList();
    }

    public int countByAplicacionGerenciaPerfil(int idAplicacion, int idGerenciaAprobadora, int idPerfil, Short activo) {
        Query q = em.createNamedQuery("PrivilegioSolicitud.countByAplicacionGerenciaPerfil")
                .setParameter("idAplicacion", idAplicacion)
                .setParameter("idGerenciaAprobadora", idGerenciaAprobadora)
                .setParameter("idPerfil", idPerfil)
                .setParameter("activo", activo);

        return ((Long) q.getSingleResult()).intValue();
    }

    public List<PrivilegioSolicitud> findByGerencia(int idGerenciaAprobadora) {
        return em.createNamedQuery("PrivilegioSolicitud.findByGerenciaAprobadora")
                .setParameter("idGerenciaAprobadora", idGerenciaAprobadora)
                .setParameter("activo", EstadoActividadEnum.ACTIVO.getId())
                .getResultList();
    }

    public int getPrivilegioSolicitudCount() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        Root<PrivilegioSolicitud> rt = cq.from(PrivilegioSolicitud.class);
        cq.select(em.getCriteriaBuilder().count(rt));
        Query q = em.createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }

    public int getPrivilegioCount(PrivilegioSolicitudDto dataTransfer) {
        CriteriaBuilder builder = em.getCriteriaBuilder();
        CriteriaQuery cQuery = builder.createQuery();
        Root<PrivilegioSolicitud> root = cQuery.from(PrivilegioSolicitud.class);
        cQuery.select(builder.count(root));

        List<Predicate> predicados = construirPredicados(dataTransfer, root);

        if (!predicados.isEmpty()) {
            //WHERE [...]
            cQuery.where(predicados.toArray(new Predicate[0]));
        }

        Query query = em.createQuery(cQuery);

        return ((Long) query.getSingleResult()).intValue();
    }

}
